#include "renderarea.h"
#include "ui_renderarea.h"
RenderArea::RenderArea(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::RenderArea),random_engine(static_cast<unsigned int>(time(0)))
    ,undirected_graph(std::vector<std::vector<int>>(maxPointNum, std::vector<int>(maxPointNum, 0)))
    ,destination(-1,-1)
    ,departure(-1,-1)
    ,dj_graph{}
{
    ui->setupUi(this);
    setBackgroundRole(QPalette::Base);
    setAutoFillBackground(true);
    qDebug()<<"destination is :"<<destination;
    qDebug()<<"departure is :"<<departure;
    destination_pixmap.load("../../../images/终点.png");
    departure_pixmap.load("../../../images/起点.png");

}

RenderArea::~RenderArea()
{
    delete ui;
}
void RenderArea::paintEvent(QPaintEvent *event){
    QPainter painter(this);
    // 设置点画笔
    int width = 8;
    Qt::PenStyle style = Qt::PenStyle(Qt::SolidLine);
    Qt::PenCapStyle cap = Qt::PenCapStyle(Qt::RoundCap);
    Qt::PenJoinStyle join = Qt::PenJoinStyle(Qt::RoundJoin);
    pen = QPen(Qt::gray,width,style,cap,join);
    painter.setPen(pen);
    // 抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    for(const QPoint& p:point_list){
        // 绘制点
        painter.drawPoint(p);
    }
    // 重新设置线的画笔
    width = 3;
    pen = QPen(Qt::gray,width,style,cap,join);
    painter.setPen(pen);
    // 绘制保存的线
    for(const QLine& line:line_list){
        painter.drawLine(line);
    }
    // 绘制新的线
    if(selectOne!=-1&&selectTwo!=-1&&selectOne!=selectTwo){
        if(isLineBetweenTwoPoint(selectOne,selectTwo))return;
        setUnDirectionGraphStateBetweenTwoPoint(selectOne,selectTwo,1);
        QLine line = QLine(point_list[selectOne],point_list[selectTwo]);
        line_list.push_back(line);
        // 添加线的时候更新dj_graph
        // 首先获取selectOne和selectTwo两个，哈哈看了一下这个selectOne和Two就是对应的index不得不佩服上周的我当时写代码就已经给后面留好了扩展性。
        // 计算权值
        int weight = Utils::euclideanDistanceSquared(point_list[selectOne],point_list[selectTwo]);
        dj_graph[selectOne].push_back({selectTwo,weight});
        dj_graph[selectTwo].push_back({selectOne,weight});
        clearSelectTwoPoint();
        qDebug()<<"绘制了一条线";
        painter.drawLine(line);
    }
    // 绘制终点
    {
        int x = destination.x();
        int y = destination.y();
        if(x!=-1&&y!=-1){
            painter.drawPixmap(x-25,y-40,destination_pixmap);
        }
    }
    // 绘制起点
    {
        int x = departure.x();
        int y = departure.y();
        if(x!=-1&&y!=-1){
            painter.drawPixmap(x-24,y-40,departure_pixmap);
        }
    }
    // 打印当前dj_graph
    showDjGraph();
}
void RenderArea::addRandomPoint(){
    // 其实不知道会不会出现重复点？？？要多一个检查重复点的步骤
    int width = this->width();
    int height = this->height();
    dist_x = std::uniform_int_distribution<int>(0, width - 1);
    dist_y = std::uniform_int_distribution<int>(0, height - 1);
    int x = dist_x(random_engine);
    int y = dist_y(random_engine);
    qDebug()<<"x:"<<x<<"y:"<<y;
    Utils::addPoint(this,x,y);
    update();
}

void RenderArea::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton){
        handleLeftButtonClick(event);
    }else if(event->button()==Qt::RightButton){
        handleRightButtonClick(event);
    }
}
void RenderArea::handleLeftButtonClick(QMouseEvent* event){
    QPoint pos = event->pos();
    qDebug()<<"鼠标左键被点击了，点击位置为："<<pos;
    // 如果以pos为左上角的矩形区域内包含随机点
    int index;
    if((index = Utils::getIdxOfRandomPointInRect(*this,pos))>=0){
        // 如果第一个都没点说明现在点的是第一个
        if(selectOne==-1){
            selectOne = index;
        }else if(selectTwo==-1){
            selectTwo = index;
        }else{
            // 两个都点了就删除记录重来
            clearSelectTwoPoint();
            selectOne = index;
        }
    }else{
        clearSelectTwoPoint();
    }
    qDebug()<<"selectOne:"<<selectOne<<"selectTwo:"<<selectTwo;
    update();
}

void RenderArea::handleRightButtonClick(QMouseEvent* event){
    qDebug()<<"点击了鼠标右键";
    // 只有当在线上或者点上点击右键才会弹出弹窗
    QPoint pos = event->pos();
    int point_index = Utils::getIdxOfRandomPointInRect(*this,pos);
    int line_index = Utils::getIdxOfLine(*this,pos);
    if(point_index==-1&&line_index==-1){
        qDebug()<<"点的是空白区域";
        Utils::buildNormalMenu(this,pos);
    }else if((point_index!=-1&&line_index!=-1)||(point_index!=-1&&line_index==-1)){
        qDebug()<<"点击的是点";
        Utils::buildPointMenu(this,pos,point_index);
    }else{
        qDebug()<<"点击的是线";
        Utils::buildLineMenu(this,pos,line_index);
    }
}

void RenderArea::setUnDirectionGraphStateBetweenTwoPoint(int p1_index,int p2_index,int state){
    undirected_graph[p1_index][p2_index] = state;
    undirected_graph[p2_index][p1_index] = state;
}
void RenderArea::clearSelectTwoPoint(){
    selectOne = -1;
    selectTwo = -1;
}
bool RenderArea::isLineBetweenTwoPoint(int p1_index,int p2_index){
    return undirected_graph[selectOne][selectTwo]||undirected_graph[selectTwo][selectOne];
}
